﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nova.Parsing.GoldParser.Semantic;
using Nova.Parsing.Tokens;

namespace Nova.Parsing.Constructs
{
    public sealed class MemoryVariableConstruct : VariableConstruct
    {
        private ExpressionConstruct m_Value;
        private MemoryVariableParameterSetConstruct m_Params;

        [Rule(@"<Memory Variable> ::= '@' '(' <Expression> ')'")]
        public MemoryVariableConstruct(IgnoredToken iA, IgnoredToken iB, ExpressionConstruct value, IgnoredToken iC)
        {
            m_Value = value;
        }

        [Rule(@"<Memory Variable> ::= '@' '(' <Expression> <Memory Variable Params> ')'")]
        public MemoryVariableConstruct(IgnoredToken iA, IgnoredToken iB, ExpressionConstruct value, MemoryVariableParameterSetConstruct paramSet, IgnoredToken iC)
        {
            m_Value = value;
            m_Params = paramSet;
        }

        public ExpressionConstruct Value
        {
            get { return m_Value; }
        }

        public MemoryVariableParameterSetConstruct Parameters
        {
            get { return m_Params; }
        }
    }

    public class MemoryVariableParameterSetConstruct : NovaConstruct, IEnumerable<MemoryVariableParameterConstruct>
    {
        private MemoryVariableParameterConstruct m_Param;
        private MemoryVariableParameterSetConstruct m_NextSet;

        [Rule(@"<Memory Variable Params> ::= <Memory Variable Params> <Memory Variable Param>")]
        public MemoryVariableParameterSetConstruct(MemoryVariableParameterSetConstruct pars, MemoryVariableParameterConstruct par)
        {
            m_Param = par;
            m_NextSet = pars;
        }

        [Rule(@"<Memory Variable Params> ::= ',' <Memory Variable Param>")]
        public MemoryVariableParameterSetConstruct(IgnoredToken iA, MemoryVariableParameterConstruct par)
        {
            m_Param = par;
            m_NextSet = null;
        }

        public MemoryVariableParameterConstruct CurrentParameter
        {
            get { return m_Param; }
        }

        public MemoryVariableParameterSetConstruct NextParameterSet
        {
            get { return m_NextSet; }
        }

        #region IEnumerable<MemoryVariableParameterConstruct> Members

        public IEnumerator<MemoryVariableParameterConstruct> GetEnumerator()
        {
            for (MemoryVariableParameterSetConstruct set = this; set != null; set = set.NextParameterSet)
            {
                if (set.CurrentParameter != null)
                {
                    yield return set.CurrentParameter;
                }
            }
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }

    public class MemoryVariableParameterConstruct : NovaConstruct
    {
        private MemoryVariableOptionToken m_OptionName;
        private ValueToken m_Value;

        [Rule(@"<Memory Variable Param> ::= <Memory Variable Param Option> '=' <Constant>")]
        public MemoryVariableParameterConstruct(MemoryVariableOptionToken option, OperatorToken iA, ValueToken constantValue)
        {
            m_OptionName = option;
            m_Value = constantValue;
        }

        public MemoryVariableOptionToken Option
        {
            get { return m_OptionName; }
        }

        public ValueToken Value
        {
            get { return m_Value; }
        }
    }
}
